#include "jglogtools.h"

#ifdef _WIN32
#include <io.h>
#pragma warning(disable : 4996)
#else

#include <sys/stat.h>
#endif


void JGLogTools_Init(JGLogTools_LEVEL level, JGLogTools_OUTSTATE outState)
{
	JGLogToolsBase._outState = outState;
	JGLogToolsBase._level = level;

#ifdef _WIN32
	JGLogToolsBase.g_hMutex = CreateMutex(NULL, FALSE, NULL);
#else
	pthread_mutex_init(&JGLogToolsBase.g_hMutex, NULL);
#endif

	memset(JGLogToolsBase._filepath, 0, JGLOGTOOLS_FILENAME_LEN);
	sprintf(JGLogToolsBase._filepath, "logs");

#ifdef _WIN32
	if (_access(JGLogToolsBase._filepath, 0) != 0)
		mkdir(JGLogToolsBase._filepath);
#else
	mkdir(JGLogToolsBase._filepath,S_IRWXG);
#endif

	JGLogTools_CreateLogFile();
}

void JGLogTools_CreateLogFile()
{
	_JGLogTools_Lock();

	if (JGLogToolsBase._fp)
	{
		fclose(JGLogToolsBase._fp);
		JGLogToolsBase._fp = NULL;
	}

	memset(JGLogToolsBase._filename, 0, JGLOGTOOLS_FILENAME_LEN);
	sprintf(JGLogToolsBase._filename, "%s/%s.log", JGLogToolsBase._filepath, _JGLogTools_GetNowTimeStr("%d-%d-%d"));

	time_t rawtime = time(0);
	JGLogToolsBase._nowPfileTime = gmtime(&rawtime);

	memcpy(&JGLogToolsBase._pfileTime, JGLogToolsBase._nowPfileTime, sizeof(JGLogToolsBase._pfileTime));

	JGLogToolsBase._fp = fopen(JGLogToolsBase._filename, "a");

	_JGLogTools_UnLock();
}


#ifdef _WIN32

void _JGLogTools_Lock()
{
	WaitForSingleObject(JGLogToolsBase.g_hMutex, INFINITE); //等待互斥量
}

void _JGLogTools_UnLock()
{
	ReleaseMutex(JGLogToolsBase.g_hMutex); //释放互斥量
}


#else

void _JGLogTools_Lock()
{
	pthread_mutex_lock(&JGLogToolsBase.g_hMutex);
}

void _JGLogTools_UnLock()
{
	pthread_mutex_unlock(&JGLogToolsBase.g_hMutex);
}
#endif




void JGLogTools_Clear()
{
	_JGLogTools_Lock();

	if (JGLogToolsBase._fp)
	{
		fclose(JGLogToolsBase._fp);
		JGLogToolsBase._fp = NULL;
	}

	_JGLogTools_UnLock();

#ifdef _WIN32
	CloseHandle(JGLogToolsBase.g_hMutex);
#else
	pthread_mutex_destroy(&JGLogToolsBase.g_hMutex);
#endif
}

void JGLogTools_Log(JGLogTools_LEVEL level, const char *fileDesc, int lineNum, const char *data, ...)
{
	if (JGLogToolsBase._outState >= 3)
	{
		return;
	}

	_JGLogTools_Lock();

	memset(JGLogToolsBase._vbuf, 0, JGLOGTOOLS_VBBUF_LEN);
	va_list ap;
	va_start(ap, data);
	vsnprintf(JGLogToolsBase._vbuf, sizeof(JGLogToolsBase._vbuf), data, ap);
	va_end(ap);

	memset(JGLogToolsBase._logbuf, 0, JGLOGTOOLS_LOGBBUF_LEN);
	sprintf(JGLogToolsBase._logbuf, "[%s]:[%s]:[%s:%d]=>%s \n", _JGLogTools_GetNowTimeStr(NULL), _JGLogTools_getLevelRemark(&level), fileDesc, lineNum, JGLogToolsBase._vbuf);

	if (JGLogToolsBase._outState == 0 || JGLogToolsBase._outState == 2)
	{
		printf(JGLogToolsBase._logbuf);
	}

	// write file
	if ((JGLogToolsBase._outState == 1 || JGLogToolsBase._outState == 2) && JGLogToolsBase._level <= level)
	{
		_JGLogTools_WriteFile(JGLogToolsBase._logbuf);
	}

	_JGLogTools_UnLock();
}

char *_JGLogTools_GetNowTimeStr(char *strformat)
{
	if (!strformat)
	{
		strformat = "%d-%d-%d %d:%d:%d";
	}
	memset(JGLogToolsBase._timeBuf, 0, JGLOGTOOLS_TIMEBBUF_LEN);
	time_t rawtime = time(0);
	struct tm *p;

	p = gmtime(&rawtime);

	snprintf(JGLogToolsBase._timeBuf, JGLOGTOOLS_TIMEBBUF_LEN, strformat, 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, 8 + p->tm_hour, p->tm_min, p->tm_sec);
	return &JGLogToolsBase._timeBuf;
}

void _JGLogTools_WriteFile(char *strlog)
{
	time_t rawtime = time(0);
	JGLogToolsBase._nowPfileTime = gmtime(&rawtime);

	if (JGLogToolsBase._nowPfileTime->tm_year != JGLogToolsBase._pfileTime.tm_year || JGLogToolsBase._nowPfileTime->tm_mon != JGLogToolsBase._pfileTime.tm_mon || JGLogToolsBase._nowPfileTime->tm_mday != JGLogToolsBase._pfileTime.tm_mday
		//|| JGLogToolsBase._nowPfileTime->tm_min != JGLogToolsBase._pfileTime.tm_min
		//|| JGLogToolsBase._nowPfileTime->tm_hour != JGLogToolsBase._pfileTime.tm_hour
	)
	{
		JGLogTools_CreateLogFile();
	}

	if (JGLogToolsBase._fp)
	{
		fputs(strlog, JGLogToolsBase._fp);
		fflush(JGLogToolsBase._fp);
	}
}

char *_JGLogTools_getLevelRemark(JGLogTools_LEVEL *level)
{
	switch (*level)
	{
	case JGLOGTOOLS_LEVEL_DEBUG:
		return "DEBUG";
	case JGLOGTOOLS_LEVEL_RINFO:
		return "INFO";
	case JGLOGTOOLS_LEVEL_RWARNING:
		return "WARNING";
	case JGLOGTOOLS_LEVEL_RERROR:
		return "ERROR";
	default:
		break;
	}
	return "NULL";
}
